iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0

今天,我們要來作Alpine Linux的initramfs bootstrapping。
在近代的大型distro中,多半都會善用early stage userspace,去進行比較複雜的rootfs初始化;各家的initramfs風格、打造方式可以差距到非常大,例如Arch Linux的工具是mkinitcpio、Gentoo的則是Dracut、Debian體系則是initramfs-tools

可是雖然風格迴異,這些initramfs的基本精神與流程皆是:從/proc/cmdline去拿到kernel boot arguements,然後爬看看有沒有initramfs要預處理的option,例如可能是nbd啦、或著initramfs特有的特技,例如Gentoo可以支援livenet這個透過http去拿rootfs的方式;然後處理好rootfs mounting後,便會透過 switch_root 或著 pivot_root的方式去更換root node、然後啟動rootfs上的 init system ,例如 systemd 或著 openrc 等等。

然而,這邊一樣有個雞蛋問題,那就是這些initramfs的生成,通常是在一個native的環境底下,進行self-bootstrapping的;但是我們現在還沒有native的環境可以用,那怎麼辦呢?依筆者前年的作法,那便是去偷Alpine on ARMv7的來用XDDDDD

首先我們去 Alpine 官網下載 Generic ARM (ARMv7) 的 tar 包下來,解壓縮完,可以在boot資料夾底下看到 initramfs-lts 這個gzip壓縮過的cpio檔案。那麼,就來拆包吧:

mkdir extract
cd extract
cat ../initramfs-lts | gzip -d -c | cpio -idv

接著 tree 一下來看有哪些東西:

├── bin
│   ├── busybox
│   └── sh -> /bin/busybox
├── dev
├── etc
│   ├── apk
│   │   └── keys
│   │       ├── alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub
│   │       └── alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub
│   ├── fstab
│   ├── group
│   ├── mdev.conf
│   ├── modprobe.d
│   │   ├── aliases.conf
│   │   ├── blacklist.conf
│   │   ├── i386.conf
│   │   └── kms.conf
│   └── passwd
├── init
├── lib
│   ├── firmware
│   │   ├── ene-ub6250
│   │   │   ├── ms_init.bin
│   │   │   ├── msp_rdwr.bin
│   │   │   ├── ms_rdwr.bin
│   │   │   ├── sd_init1.bin
│   │   │   ├── sd_init2.bin
│   │   │   └── sd_rdwr.bin
│   │   └── qcom
│   ├── libcryptsetup.so.12 -> libcryptsetup.so.12.6.0
│   ├── libcryptsetup.so.12.6.0
│   ├── libdevmapper.so.1.02
│   ├── libkmod.so.2 -> libkmod.so.2.3.7
│   ├── libkmod.so.2.3.7
│   ├── libssl.so.1.1
│   ├── libuuid.so.1 -> libuuid.so.1.3.0
│   ├── libuuid.so.1.3.0
│   ├── libz.so.1 -> libz.so.1.2.11
│   ├── libz.so.1.2.11
│   ├── mdev
│   │   ├── dvbdev
│   │   ├── ide_links
│   │   ├── usbdev
│   │   ├── usbdisk_link
│   │   └── xvd_links
│   └── modules
│       └── 5.10.61-0-lts
│           ├── kernel
│           │   ├── arch
│           │   │   └── arm
│           │   │       └── lib
│           │   │           └── xor-neon.ko
│           │   ├── block
│           │   │   └── t10-pi.ko
......

此時,因為我們只要最基礎的骨架,firmwaremodules這部份是給wifi firmware還有一些driver的,就直接大刀闊斧的幹掉。緊接著開始去我們之前千辛萬苦打出來Alpine package repo撈出對應的骨幹來用:
sudo apk -vv --allow-untrusted -X /path/to/packages/main/ -U --arch riscv32 --root $PWD/tmp_rootfs --initdb add alpine-base mkinitfs

緊接著就是非常手工藝地,把busybox、各式 shared object一個個換進去ARM initramfs裡面。

做完替換後,我們先把這份initramfs扔進一個loop dev image裡面,給之前buildroot的rv32 qemu virt試驗看看:
``
$ qemu-system-riscv32 -M virt -bios output/images/fw_jump.elf -kernel output/images/Image -append "rootwait root=/dev/vda rw init=/init" -drive file=/path/to/images.ext2,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -netdev user,id=net0 -device virtio-net-device,netdev=net0 -nographic

OpenSBI v0.9


/ __ \ / | _ _ |
| | | |
__ ___ _ __ | (
| |
) || |
| | | | '_ \ / _ \ '_ \ ___ | _ < | |
| || | |) | __/ | | |) | |) || |
_
/| ./ _|| ||/|____/|
| |
|_|

Platform Name : riscv-virtio,qemu
Platform Features : timer,mfdeleg
Platform HART Count : 1
Firmware Base : 0x80000000
Firmware Size : 124 KB
Runtime SBI Version : 0.2

Domain0 Name : root
Domain0 Boot HART : 0
Domain0 HARTs : 0*
Domain0 Region00 : 0x80000000-0x8001ffff ()
Domain0 Region01 : 0x00000000-0xffffffff (R,W,X)
Domain0 Next Address : 0x80400000
Domain0 Next Arg1 : 0x82200000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes

Boot HART ID : 0
Boot HART Domain : root
Boot HART ISA : rv32imafdcsu
Boot HART Features : scounteren,mcounteren,time
Boot HART PMP Count : 16
Boot HART PMP Granularity : 4
Boot HART PMP Address Bits: 32
Boot HART MHPM Count : 0
Boot HART MHPM Count : 0
Boot HART MIDELEG : 0x00000222
Boot HART MEDELEG : 0x0000b109
[ 0.000000] Linux version 5.10.7 (ruinland@ruinland-x1c) (riscv32-buildroot-linux-gnu-gcc.br_real (Buildroot 2021.08-235-g287a359090) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #2 SMP Sun Sep 12 22:40:18 CST 2021
[ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80400000
[ 0.000000] efi: UEFI not found.
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000080400000-0x0000000087ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000080400000-0x0000000087ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000080400000-0x0000000087ffffff]
[ 0.000000] SBI specification v0.2 detected
[ 0.000000] SBI implementation ID=0x1 Version=0x9
[ 0.000000] SBI v0.2 TIME extension detected
[ 0.000000] SBI v0.2 IPI extension detected
[ 0.000000] SBI v0.2 RFENCE extension detected
[ 0.000000] SBI v0.2 HSM extension detected

...

[ 0.669946] EXT4-fs (vda): mounting ext2 file system using the ext4 subsystem
[ 0.679685] EXT4-fs (vda): warning: mounting unchecked fs, running e2fsck is recommended
[ 0.697676] EXT4-fs (vda): mounted filesystem without journal. Opts: (null)
[ 0.699126] ext2 filesystem being mounted at /root supports timestamps until 2038 (0x7fffffff)
[ 0.700403] VFS: Mounted root (ext2 filesystem) on device 254:0.
[ 0.706050] devtmpfs: mounted
[ 0.761174] Freeing unused kernel memory: 204K
[ 0.763022] Run /init as init process
[ 1.348089] Alpine Init 3.5.0-r0
Alpine Init 3.5.0-r0
[ 1.362497] Loading boot drivers...

  • Loading boot drivers: [ 1.418605] Loading boot drivers: ok.
    ok.
    ln: /etc/mtab: File exists
    [ 1.450453] Mounting root...
  • Mounting root: [ 1.472526] nlplug-findfs[59]: unhandled signal 7 code 0x2 at 0x95a7a5b0 in ld-musl-riscv32-sf.so.1[95a7d000+c7000]
    [ 1.473890] CPU: 0 PID: 59 Comm: nlplug-findfs Not tainted 5.10.7 #2
    [ 1.474513] epc: 95af03dc ra : 95afe6e0 sp : 9db524e0
    [ 1.474891] gp : 95a7d000 tp : 95b46f28 t0 : 00000002
    [ 1.475260] t1 : 0004b8c7 t2 : 00000007 s0 : 9db52998
    [ 1.475645] s1 : 0004b000 a0 : 95a7a5b0 a1 : 00000000
    [ 1.476089] a2 : 00000a50 a3 : 00000fff a4 : fffff000
    [ 1.476551] a5 : 00000000 a6 : 00000000 a7 : 000000de
    [ 1.477002] s2 : 95a30000 s3 : 00000000 s4 : 95a30000
    [ 1.477654] s5 : 000000c0 s6 : 00000000 s7 : 00000003
    [ 1.478050] s8 : 00000005 s9 : 95b45a6c s10: 0004b000
    [ 1.478450] s11: 9db5254c t3 : 95b45288 t4 : 00000000
    [ 1.478868] t5 : 00000000 t6 : 00000020
    [ 1.479148] status: 00004020 badaddr: 95a7a5b0 cause: 0000000f
    Bus error
    mount: mounting /dev/vda on /sysroot failed: No such file or directory
    [ 1.575751] Mounting root: failed.
    failed.
    initramfs emergency recovery shell launched. Type 'exit' to continue boot
    sh: can't access tty; job control turned off
    / #

雖然 `nlplug-findfs` 這隻Alpine initramfs拿來rootfs find and mount的helper會trigger runtime failure,但那可能是因為我們還沒有給他正確root dev的關係,我們下一章,就來debug吧~

上一篇
Alpine Linux Porting (一點二?)
下一篇
Alpine Linux Porting (一點四?)
系列文
Port Alpine Linux to open source RISC-V platform30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言